package org.gbif.crawler.ws;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID;

import com.google.common.base.Preconditions;

/**
 * A class to demonstrate what ZK needs to provide.
 * TODO: write equals(), hashcode() toString() like a good dev should
 */
public class DatasetProcessStatus {

  public enum Protocol {
    DIGIR, BioCASe, TAPIR, UNKNOWN
  };

  private final URI address;
  private final UUID datasetKey;
  private final Integer declaredCount; // not Optional<Integer> to simplify JSON
  private final Protocol protocol;
  private String status;
  private int errors;
  private int pagesCrawled;
  private int pagesFragmented;
  private int fragmentsGenerared;
  private int fragmentsPersisted;
  private int recordsCreated;
  private int recordsInterpreted;

  // utility builder
  public static DatasetProcessStatus of(String protocol, String url, String uuid, String count)
    throws URISyntaxException {
    Preconditions.checkNotNull(protocol);
    Preconditions.checkNotNull(url);
    Preconditions.checkNotNull(uuid);
    Preconditions.checkNotNull(count);
    Protocol p = null;
    if ("digir".equalsIgnoreCase(protocol)) {
      p = Protocol.DIGIR;
    } else if ("tapir".equalsIgnoreCase(protocol)) {
      p = Protocol.TAPIR;
    } else if ("biocase".equalsIgnoreCase(protocol)) {
      p = Protocol.BioCASe;
    }
    Preconditions.checkNotNull(p, "Protocol could not be parsed from %s", protocol);
    return new DatasetProcessStatus(new URI(url), UUID.fromString(uuid), Integer.parseInt(count), p);
  }

  public DatasetProcessStatus(URI address, UUID datasetKey, Integer declaredCount, Protocol protocol, String status) {
    this.address = address;
    this.datasetKey = datasetKey;
    this.declaredCount = declaredCount;
    this.protocol = protocol;
    this.status = status;
  }

  public DatasetProcessStatus(URI address, UUID datasetKey, Integer declaredCount, Protocol protocol) {
    this.address = address;
    this.datasetKey = datasetKey;
    this.declaredCount = declaredCount;
    this.protocol = protocol;
  }

  public DatasetProcessStatus(URI address, UUID datasetKey, Protocol protocol) {
    this.address = address;
    this.datasetKey = datasetKey;
    this.protocol = protocol;
    this.declaredCount = null; // explicitly
  }

  public String getStatus() {
    return status;
  }

  public void setStatus(String status) {
    this.status = status;
  }

  public int getErrors() {
    return errors;
  }

  public void setErrors(int errors) {
    this.errors = errors;
  }

  public int getPagesCrawled() {
    return pagesCrawled;
  }

  public void setPagesCrawled(int pagesCrawled) {
    this.pagesCrawled = pagesCrawled;
  }

  public int getPagesFragmented() {
    return pagesFragmented;
  }

  public void setPagesFragmented(int pagesFragmented) {
    this.pagesFragmented = pagesFragmented;
  }

  public int getFragmentsGenerared() {
    return fragmentsGenerared;
  }

  public void setFragmentsGenerared(int fragmentsGenerared) {
    this.fragmentsGenerared = fragmentsGenerared;
  }

  public int getFragmentsPersisted() {
    return fragmentsPersisted;
  }

  public void setFragmentsPersisted(int fragmentsPersisted) {
    this.fragmentsPersisted = fragmentsPersisted;
  }

  public int getRecordsCreated() {
    return recordsCreated;
  }

  public void setRecordsCreated(int recordsCreated) {
    this.recordsCreated = recordsCreated;
  }

  public int getRecordsInterpreted() {
    return recordsInterpreted;
  }

  public void setRecordsInterpreted(int recordsInterpreted) {
    this.recordsInterpreted = recordsInterpreted;
  }

  public URI getAddress() {
    return address;
  }

  public UUID getDatasetKey() {
    return datasetKey;
  }

  public Integer getDeclaredCount() {
    return declaredCount;
  }

  public Protocol getProtocol() {
    return protocol;
  }

  public void incrementErrors(int i) {
    errors = errors + i > 0 ? errors + i : 0; // overflow reset to 0
  }

  public void incrementPagesCrawled(int i) {
    pagesCrawled = pagesCrawled + i > 0 ? pagesCrawled + i : 0; // overflow reset to 0
  }

  public void incrementPagesFragmented(int i) {
    pagesFragmented = pagesFragmented + i > 0 ? pagesFragmented + i : 0; // overflow reset to 0
  }

  public void incremenFragmentsGenerared(int i) {
    fragmentsGenerared = fragmentsGenerared + i > 0 ? fragmentsGenerared + i : 0; // overflow reset to 0
  }

  public void incrementFragmentsPersisted(int i) {
    fragmentsPersisted = fragmentsPersisted + i > 0 ? fragmentsPersisted + i : 0; // overflow reset to 0
  }

  public void incrementRecordsCreated(int i) {
    recordsCreated = recordsCreated + i > 0 ? recordsCreated + i : 0; // overflow reset to 0
  }

  public void incrementRecordsInterpreted(int i) {
    recordsInterpreted = recordsInterpreted + i > 0 ? recordsInterpreted + i : 0; // overflow reset to 0
  }
}